package com.qf.commons.event.mq.rabbitmq.config;

import com.qf.commons.core.utils.ApplicationUtils;
import com.qf.commons.event.apply.consumer.EventHandler;
import com.qf.commons.event.apply.consumer.IEventHandler;
import com.qf.commons.event.mq.rabbitmq.commons.Constacts;
import com.qf.commons.event.mq.rabbitmq.handler.RabbitMQProduceStandardHandler;
import com.qf.commons.event.mq.rabbitmq.listener.MsgListener;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotationUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * RabbitMQ的配置类
 */
@Configuration
public class RabbitMqAutoConfiguration {

    /**
     * 发布端的配置
     */
    @Configuration
    public static class RabbitMqProducerConfiguration{

        public RabbitMqProducerConfiguration(){
            System.out.println("RabbitMQ发布端配置加载！！！！");
        }

        /**
         * 实时的交换机
         * @return
         */
        @Bean
        public DirectExchange getDirectExchange(){
            return new DirectExchange(Constacts.EVENT_EXCHANGE_NAME);
        }

        /**
         * 延迟交换机
         * @return
         */
        @Bean
        public CustomExchange getDelayExchange(){
            Map<String, Object> params = new HashMap<>();
            params.put("x-delayed-type", "topic");
            return new CustomExchange(Constacts.DELAY_EXCHANGE_NAME, "x-delayed-message", true, false, params);
        }

        @Bean
        public RabbitMQProduceStandardHandler getMqProduceStandardHandler(){
            return new RabbitMQProduceStandardHandler();
        }
    }

    /**
     * 消费端端的配置
     */
    @Configuration
    @ConditionalOnBean(IEventHandler.class)
    public static class RabbitMqConsumerConfiguration{

        public RabbitMqConsumerConfiguration(){
            System.out.println("RabbitMQ消费端配置加载！！！！");
        }

        @Value("${spring.application.name}")
        private String appName;

        @Autowired
        private List<IEventHandler> eventHandlers;

        //配置队列的绑定
        @Bean
        public Queue getQueue(){
            return new Queue("event-" + appName, true);
        }

        //配置队列和交换机的绑定
        @Bean
        public Binding getBinding(DirectExchange getDirectExchange, Queue getQueue){
//            return BindingBuilder.bind(getQueue).to(getDirectExchange).with(??????);

            //循环所有的开发者 提供的事件处理器
            for (IEventHandler eventHandler : eventHandlers) {
                //获取事件处理器上的注解
                EventHandler eventHandlerAnnotation = AnnotationUtils.findAnnotation(eventHandler.getClass(), EventHandler.class);
                if (eventHandlerAnnotation == null) continue;

                //获取注解中的事件类型
                String eventType = eventHandlerAnnotation.value();
                //将队列和交换机绑定，绑定的路由键，就是消费端 关注的事件类型
                Binding binding = BindingBuilder
                        .bind(getQueue)
                        .to(getDirectExchange)
                        .with(eventType);

                //手动将这个Bean注册到SpringIOC容器中
                ApplicationUtils.registerBean(binding);
            }

            return null;
        }

        /**
         * 消费者队列 绑定 延迟交换机
         * @return
         */
        @Bean
        public Binding getDelayBinding(CustomExchange getDelayExchange, Queue getQueue){
            //循环所有的开发者 提供的事件处理器
            for (IEventHandler eventHandler : eventHandlers) {
                //获取事件处理器上的注解
                EventHandler eventHandlerAnnotation = AnnotationUtils.findAnnotation(eventHandler.getClass(), EventHandler.class);
                if (eventHandlerAnnotation == null) continue;

                //获取注解中的事件类型
                String eventType = eventHandlerAnnotation.value();
                //将队列和交换机绑定，绑定的路由键，就是消费端 关注的事件类型
                Binding binding = BindingBuilder
                        .bind(getQueue)
                        .to(getDelayExchange)
                        .with(eventType).and(new HashMap<>());

                //手动将这个Bean注册到SpringIOC容器中
                ApplicationUtils.registerBean(binding);
            }

            return null;
        }

        @Bean
        public MsgListener getMsgListener(){
            return new MsgListener();
        }
    }
}
